// Copyright 2012 Google Inc. All rights Reserved.
package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"runtime"
	"time"

	"code.google.com/p/gomonitor/collector"
	cfg "code.google.com/p/gomonitor/config"
	"code.google.com/p/gomonitor/tsdb"
	"code.google.com/p/gomonitor/tsdb/file"
	"code.google.com/p/gomonitor/tsdb/sqlite"
)

func init() {
	if runtime.NumCPU() > 1 {
		runtime.GOMAXPROCS(runtime.NumCPU())
	} else {
		runtime.GOMAXPROCS(2)
	}
}

// TODO(jwall): Autocomplete source and variable names.
// TODO(jwall): Factor out the data inputs into something pluggable.
// TODO(jwall): Detect config changes.

var (
	sqldb           = flag.String("sqlite", "", "location of the tsdb database file (do not set both this and filedb)")
	filedb          = flag.String("filedb", "", "location of the tsdb file directory (do not set both this and sqlite)")
	fileBlockSize   = flag.Int("blocksize", 30, "blocksize to use for filedb")
	maxHoursPerFile = flag.Int("file_duration", 24, "max duration for a single timeseries file in hours.")
	listen          = flag.String("http", "", "host:port for http serving")
	poll            = flag.Int("polltime", 0, "poll interval in seconds to gather statistics")
	configFile      = flag.String("config", "", "config file with the vars and rules for monitoring.")
	help            = flag.Bool("help", false, "display this help")
)

func main() {
	flag.Parse()
	if *help {
		flag.PrintDefaults()
		return
	}
	if *sqldb != "" && *filedb != "" {
		log.Print("Can't set both sqlite and filedb")
		flag.PrintDefaults()
		os.Exit(1)
	}
	if *sqldb == "" && *filedb == "" {
		log.Print("You must set one of sqlite or filedb")
		flag.PrintDefaults()
		os.Exit(1)
	}
	if *poll < 1 {
		log.Print("You must set a polltime")
		flag.PrintDefaults()
		os.Exit(1)
	}
	config, err := cfg.Read(*configFile)
	if err != nil {
		log.Print(err)
		return
	}
	var tdb tsdb.TsDb
	if *sqldb != "" {
		tdb, err = sqlite.New(*sqldb)
		if err != nil {
			log.Print(err)
			return
		}
	}
	if *filedb != "" {
		db := file.New(*filedb, int32(*fileBlockSize), time.Hour*time.Duration(*maxHoursPerFile), config.Metrics()...)
		defer db.Shutdown()
		tdb = tsdb.TsDb(db)
	}
	agg := tsdb.Aggregator{TsDb: tdb}
	agg.RegisterCommon()
	go collector.Main(config, &agg, *poll, *listen)
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Kill, os.Interrupt)
	defer log.Printf("Got kill or interrupt signal")
	<-c
}
